package oneD.fem.algorithm;

import inf.jlinalg.Array2DMatrix;
import inf.jlinalg.ArrayVector;
import inf.jlinalg.IMatrix;
import inf.jlinalg.IVector;

public class Tensor1 implements ITensor {

	IVector v;

	public Tensor1(IVector v) {
		this.v = v;
	}

	public Tensor1(double... v) {
		this.v = new ArrayVector(v);
	}

	@Override
	public double get(int... I) {
		return v.get(I[0]);
	}

	public IVector getA() {
		return v;
	}

	@Override
	public double trace() {
		// TODO: check trace of tensor rank 1
		return 0;
	}

	@Override
	public int rank() {
		return 1;
	}

	@Override
	public int dimension() {
		return v.getSize();
	}

	@Override
	public Object clone() {
		Tensor1 theClone = new Tensor1((IVector) this.v.clone());
		return theClone;

	}

	private boolean checkCompatible(ITensor B) {
		if (B.rank() != this.rank()) {
			System.out.println("tensor rank is not compatible");
			return false;
		}
		if (B.dimension() != this.dimension()) {
			System.out.println("tensor dimension is not compatible");
			return false;
		}
		return true;
	}

	@Override
	public ITensor contraction(ITensor B) {
		/*
		 * tensor rank 1 can't contract with lower order tensor
		 */
		return null;
	}

	@Override
	public ITensor multiply(ITensor B) {
		if (!checkCompatible(B))
			return null;
		else {
			IVector v = (IVector) this.v.clone();
			for (int i = 0; i < v.getSize(); i++)
				v.set(i, v.get(i) * B.get(i));
			return new Tensor1(v);
		}
	}

	@Override
	public double dot(ITensor B) {
		if (!checkCompatible(B))
			return 0;
		else {
			double tmp = 0;
			for (int i = 0; i < dimension(); i++)
				tmp += get(i) * B.get(i);
			return tmp;
		}
	}

	@Override
	public ITensor product(ITensor B) {
		if (!checkCompatible(B))
			return null;
		else {
			IMatrix C = new Array2DMatrix(dimension(), dimension());
			for (int i = 0; i < dimension(); i++)
				for (int j = 0; j < dimension(); j++)
					C.set(i, j, v.get(i) * B.get(j));
			return new Tensor2(C);
		}
	}

	@Override
	public Tensor1 add(double alpha, ITensor B) {
		double[] v = new double[dimension()];
		for (int i = 0; i < dimension(); i++)
			v[i] = this.v.get(i) + alpha * B.get(i);
		return new Tensor1(v);
	}

}
